<template>
  <ThreeSectionTabsPage>
    <template #tabs>
      <el-tabs v-model="currentTabName" @tab-click="handleTabClick">
        <el-tab-pane :label="$t('createTable.tabs[0]')" name="GeneralTab" />
        <el-tab-pane :label="$t('createTable.tabs[1]')" name="ColumnsTab" />
        <el-tab-pane :label="$t('createTable.tabs[2]')" name="ConstraintTab" />
        <el-tab-pane :label="$t('createTable.tabs[3]')" name="IndexesTab" />
        <el-tab-pane
          :label="$t('createTable.tabs[4]')"
          name="PartitionTab"
          :disabled="!dataMap.GeneralTab.isPartition"
        />
        <el-tab-pane :label="$t('createTable.tabs[5]')" name="DDL" />
      </el-tabs>
    </template>
    <template #center-container>
      <GeneralTab
        ref="generalref"
        v-show="currentTabName == 'GeneralTab'"
        v-model:isPartition="dataMap.GeneralTab.isPartition"
        :commonParams="commonParams"
      />
      <ColumnsTab
        ref="columnsRef"
        v-show="currentTabName == 'ColumnsTab'"
        :commonParams="commonParams"
        v-model:data="dataMap.ColumnsTab.data"
      />
      <ConstraintTab
        ref="constraintRef"
        v-show="currentTabName == 'ConstraintTab'"
        v-model:data="dataMap.ConstraintTab.data"
        :commonParams="commonParams"
        :columns="availColumns"
      />
      <IndexesTab
        ref="indexesRef"
        v-show="currentTabName == 'IndexesTab'"
        v-model:data="dataMap.IndexesTab.data"
        :commonParams="commonParams"
        :columns="availColumns"
      />
      <PartitionTab
        ref="partitionRef"
        v-show="currentTabName == 'PartitionTab'"
        :columns="availColumns"
      />
      <DDL v-show="currentTabName == 'DDL'" :data="dataMap.DDL.data" />
    </template>
    <template #page-bottom-button>
      <el-button type="primary" @click="handleSave">{{ $t('button.create') }}</el-button>
      <el-button @click="handleReset">{{ $t('button.reset') }}</el-button>
    </template>
  </ThreeSectionTabsPage>
</template>

<script lang="ts" setup>
  import { ElMessage } from 'element-plus';
  import type { TabsPaneContext } from 'element-plus';
  import { useRoute, useRouter } from 'vue-router';
  import { useTagsViewStore } from '@/store/modules/tagsView';
  import GeneralTab from './components/GeneralTab.vue';
  import PartitionTab from './components/PartitionTab.vue';
  import ColumnsTab from './components/ColumnsTab.vue';
  import ConstraintTab from './components/ConstraintTab.vue';
  import IndexesTab from './components/IndexesTab.vue';
  import DDL from './components/DDL.vue';
  import { useI18n } from 'vue-i18n';
  import { getTablespaceList } from '@/api/metaData';
  import { getCreateTableDdl, createTable } from '@/api/table';
  import { loadingInstance } from '@/utils';
  import EventBus, { EventTypeName } from '@/utils/event-bus';
  import { eventQueue } from '@/hooks/saveData';

  const route = useRoute();
  const router = useRouter();
  const TagsViewStore = useTagsViewStore();
  const tagId = TagsViewStore.getViewByRoute(route)?.id;
  const { t } = useI18n();
  const loading = ref(null);

  const currentTabName = ref('GeneralTab');
  const commonParams = reactive({
    schema: '',
    uuid: '',
  });
  const refreshParams = reactive({
    rootId: '',
    databaseId: '',
    schemaId: '',
  });
  const tablespaceList = ref<string[]>([]);
  provide('tablespaceList', tablespaceList);
  const generalref = ref<InstanceType<typeof GeneralTab>>(null);
  const columnsRef = ref<InstanceType<typeof ColumnsTab>>(null);
  const constraintRef = ref<InstanceType<typeof ConstraintTab>>(null);
  const indexesRef = ref<InstanceType<typeof IndexesTab>>(null);
  const partitionRef = ref<InstanceType<typeof PartitionTab>>(null);
  const dataMap = reactive({
    GeneralTab: {
      isPartition: false,
    },
    ColumnsTab: {
      data: [],
    },
    ConstraintTab: {
      data: [],
    },
    IndexesTab: {
      data: [],
    },
    PartitionTab: {},
    DDL: {
      data: '',
    },
  });
  const availColumns = computed(() => {
    return dataMap.ColumnsTab.data
      .filter((item) => !!item.columnName?.trim())
      .map((item) => {
        return {
          label: item.columnName,
          value: item.columnName,
          dataType: item.dataType,
        };
      });
  });

  const handleTabClick = (tab: TabsPaneContext) => {
    if (tab.paneName == 'DDL') {
      handlePreviewDdl();
    }
  };

  const getFinallyParams = () => {
    const generalValue = generalref.value.formValue;
    const partitionValue = partitionRef.value?.formValue;
    const params = {
      ...commonParams,
      tableInfo: {
        tableName: generalValue.tableName,
        exists: generalValue.ifNotExists,
        tableType: generalValue.tableType,
        oids: generalValue.oids,
        tableSpace: generalValue.tableSpace,
        fillingFactor: generalValue.fillingFactor,
        storage: generalValue.storage,
        comment: generalValue.comment,
      },
      column: dataMap.ColumnsTab.data
        .filter((item) => item.columnName)
        .map((item) => {
          return {
            operationType: 1,
            newColumnName: item.columnName,
            type: item.dataType,
            isEmpty: item.canBeNull,
            defaultValue: item.defaultValue,
            isOnly: item.isUnique,
            precision: item.precisionSize,
            scope: item.range,
            comment: item.description,
          };
        }),
      constraints: dataMap.ConstraintTab.data.map((item) => {
        return {
          type: 1,
          conName: item.constrainName,
          attName: Array.isArray(item.columnName) ? item.columnName.join(',') : '',
          conType: Array.isArray(item.constrainType) ? item.constrainType[0] : null,
          nspName:
            item.constrainType?.[0] == 'f' && item.constrainType[1] ? item.constrainType[1] : null, //foreign key namespace
          tbName:
            item.constrainType?.[0] == 'f' && item.constrainType[2] ? item.constrainType[2] : null, //foreign key tableName
          colName:
            item.constrainType?.[0] == 'f' && item.constrainType[3] ? item.constrainType[3] : null, //foreign key colName
          constraintDef: item.expression,
          conDeferrable: item.isDeffered,
          description: item.description,
        };
      }),
      indexs: dataMap.IndexesTab.data.map((item) => {
        return {
          type: 1,
          indexName: item.indexName,
          unique: item.isUnique,
          amName: item.accessMethod,
          attName: Array.isArray(item.columnName) ? item.columnName.join(',') : '',
          expression: item.expression,
          description: item.description,
        };
      }),
      partitionInfo: dataMap.GeneralTab.isPartition
        ? {
            type: partitionValue.partitionType,
            valueInterval: partitionValue.valueInterval,
            partitionName: partitionValue.partitionName,
            tableSpace: partitionValue.tableSpace,
            partitionColumn: partitionValue.partitionColumn?.join(),
            partitionValue: partitionValue.partitionValue,
          }
        : undefined,
    };
    return params;
  };
  const handlePreviewDdl = async () => {
    const params = getFinallyParams();
    const res = (await getCreateTableDdl(params)) as unknown as string;
    dataMap.DDL.data = res;
  };

  const handleSave = async () => {
    const generalValid = generalref.value?.validateForm;
    const partitionValid = partitionRef.value?.validateForm;
    try {
      await Promise.all([generalValid(), dataMap.GeneralTab.isPartition ? partitionValid() : true]);
    } catch (error) {
      currentTabName.value = error;
      return Promise.reject();
    }
    const actualColumns = dataMap.ColumnsTab.data.filter((item) => item.columnName?.trim());
    if (actualColumns.length == 0) {
      currentTabName.value = 'ColumnsTab';
      ElMessage.error(t('message.leastOneColumn'));
      return Promise.reject();
    }
    const params = getFinallyParams();
    loading.value = loadingInstance();
    try {
      await createTable(params);
      ElMessage.success(t('message.createSuccess'));
      EventBus.notify(EventTypeName.REFRESH_ASIDER, 'schema', refreshParams);
      TagsViewStore.delCurrentView(route);
      const visitedViews = TagsViewStore.visitedViews;
      router.push(visitedViews.slice(-1)[0].fullPath);
    } catch {
      return Promise.reject();
    } finally {
      loading.value.close();
    }
  };

  const handleReset = () => {
    generalref.value?.resetFields();
    partitionRef.value?.resetFields();
    dataMap.GeneralTab.isPartition = false;
    dataMap.ColumnsTab.data = [];
    dataMap.ConstraintTab.data = [];
    dataMap.IndexesTab.data = [];
    dataMap.DDL.data = '';
    if (currentTabName.value === 'PartitionTab') {
      currentTabName.value = 'GeneralTab';
    }
  };
  const fetchTablespaceList = async () => {
    const res = (await getTablespaceList({ uuid: commonParams.uuid })) as unknown as string[];
    tablespaceList.value = res;
  };

  onMounted(() => {
    const { schema, uuid, rootId, databaseId, schemaId } = route.query;
    Object.assign(commonParams, {
      schema,
      uuid,
    });
    Object.assign(refreshParams, {
      rootId,
      databaseId,
      schemaId,
    });
    nextTick(fetchTablespaceList);
    eventQueue[tagId] = () => handleSave();
  });
</script>
